﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Collections;
using TypedROBIN.Common;

namespace TypedROBIN.Imaging
{
    internal class Logger
    {
        private static ArrayList s_Queue = new ArrayList(1000);
        private static Timer s_TimeToFlush;

        static Logger()
        {
            s_TimeToFlush = new Timer();
            s_TimeToFlush.Interval = 1000;
            s_TimeToFlush.Elapsed += new ElapsedEventHandler(s_TimeToFlush_Elapsed);
            s_TimeToFlush.Enabled = true;
            s_TimeToFlush.Start();
        }

        private static void s_TimeToFlush_Elapsed(object sender, ElapsedEventArgs e)
        {
            s_TimeToFlush.Stop();
            LogData[] LogDatas = null;
            try
            {
                lock (s_Queue)
                {
                    LogDatas = s_Queue.ToArray(typeof(LogData)) as LogData[];
                    s_Queue.Clear();
                }
                LogDao dao = new LogDao();
                dao.AddRange(LogDatas);
            }
            finally
            {
                s_TimeToFlush.Start();
            }
        }

        internal static void ERROR(
            string message,
            string taskId,
            string callerIdentity)
        {
            Log(
                Level.ERROR,
                message,
                taskId,
                callerIdentity);
        }

        internal static void TRACE(
            string message,
            string taskId,
            string callerIdentity)
        {
            Log(
                Level.TRACE,
                message,
                taskId,
                callerIdentity);
        }

        internal static void INFO(
            string message,
            string taskId,
            string callerIdentity)
        {
            Log(
                Level.INFO,
                message,
                taskId,
                callerIdentity);
        }

        private static void Log(
            Level level, 
            string message, 
            string taskId,
            string callerIdentity)
        {
            LogData logData = new LogData(
                level,
                DateTime.UtcNow,
                message,
                taskId,
                callerIdentity);
            lock (s_Queue)
            {
                s_Queue.Add(logData);
            }
        }

        internal void AddRange(LogData[] datas)
        {
            if (datas != null && datas.Length > 0)
            {
                foreach (LogData ld in datas)
                {
                    lock (s_Queue)
                    {
                        s_Queue.Add(ld);
                    }
                }
            }
        }

        internal int Remove(Level level)
        {
            LogDao dao = new LogDao();
            return dao.Remove(level);
        }

        internal int Clear()
        {
            LogDao dao = new LogDao();
            return dao.Clear();
        }

        internal LogData[] GetAll(Sorting[] Sortings = null)
        {
            Sort[] sorts = SortingsToSorts(Sortings);
            if (Sortings == null || Sortings.Length==0)
            {
                sorts = new Sort[0];
            }
            LogDao dao = new LogDao();
            return dao.GetAll(sorts);
        }

        private Sort[] SortingsToSorts(Sorting[] Sortings)
        {
            Sort[] sorts = new Sort[0];
            if (Sortings == null || Sortings.Length == 0)
            {
                return sorts;
            }
            sorts = new Sort[Sortings.Length];
            for (int i = 0; i < Sortings.Length; i++)
            {
                sorts[i] = new Sort(LogData.ORMapping(Sortings[i].LogField), Sortings[i].Order);
            }
            return sorts;
        }
    }
}
